package com.foreveross.proxyip.local;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.foreveross.crawl.common.cfg.PropertyUtils;
import com.foreveross.proxyip.ProxyIpModel;
import com.foreveross.proxyip.ProxyipProperties;
import com.foreveross.proxyip.ProxyipProvideException;

/**
 * 简单代理ip池
 * <p>
 * 一个带有实例id代理ip池，默认实例ID为DefaultInstance<br/>
 * 一般地，在使用代理ip过程中，若同一个ip针对同一抓取渠道时，会出现渠道阻抗(拒绝访问，出404错误等)， 使用渠道ip池则可以减少这种阻抗<br/>
 * 在使用方(抓取引警)获到实例后，可以从代理ip服务方获取ip存入该池，抓取过程中每请求一次从池中取一个ip对象在client中设置。
 *
 * @author xiangsf
 *
 */
public class ProxyIpSimplePool {
	public Logger logger = LoggerFactory.getLogger(ProxyIpSimplePool.class);
	public final static String DEFAULT_PROXY_POOL_INSTANCEID = "DefaultInstance";
	public final static String INTER_PROXY_POOL_INSTANCEID = "InterInstance";

	public final static int PROXYIP_POOL_MAXSIZE = 5;

	public final static int PROXYIP_DURATIONOFVALIDITY = 3600000;

	public final static int PROXYIP_MAX_REPEAT_USECOUNT = 10;

	// 池中的代理ip集合
	protected List<ProxyIpModel> proxyIps = null;
	// 池中的中转代理IP
	protected List<ProxyIpModel> proxyTempIps = null;
	// 池的实例ID
	protected String poolInstanceId = DEFAULT_PROXY_POOL_INSTANCEID;
	// 池的最大存储ip数量
	protected int maxSize = PROXYIP_POOL_MAXSIZE;
	// 一个IP的可重复使用次数
	protected int maxRepeatCount = PROXYIP_MAX_REPEAT_USECOUNT;
	// 池中代理ip失效时长，单位毫秒
	protected int durationOfValidity = PROXYIP_DURATIONOFVALIDITY;

	public ProxyIpSimplePool(String poolInstanceId) {
		maxSize = PropertyUtils.getIntProperty("proxyip.provider.simplepool.maxsize", ProxyipProperties.CONFIG_FILE, PROXYIP_POOL_MAXSIZE);
		durationOfValidity = PropertyUtils.getIntProperty("proxyip.provider.simplepool.durationOfValidity", ProxyipProperties.CONFIG_FILE, PROXYIP_DURATIONOFVALIDITY);
		maxRepeatCount = PropertyUtils.getIntProperty("proxyip.provider.repeat.use.count", ProxyipProperties.CONFIG_FILE, PROXYIP_DURATIONOFVALIDITY);
		proxyIps = new Vector<ProxyIpModel>(maxSize);
		proxyTempIps = new Vector<ProxyIpModel>(maxSize);
		this.poolInstanceId = poolInstanceId;
	}

	public String getPoolInstanceId() {
		return poolInstanceId;
	}

	public synchronized boolean removeProxyIp(ProxyIpModel model) {
		logger.info(String.format("simple pool proxyIps size:%s, proxyTempIps size:%s ", proxyIps.size(), proxyTempIps.size()));
		return proxyTempIps.remove(model);
	}

	/**
	 * 获得可用的IP
	 *
	 * @return
	 */
	public synchronized ProxyIpModel getProxyIp() {
		// 有则直接获得对象，并称除
		if (proxyIps != null && !proxyIps.isEmpty()) {
			// 如果超时，则拿下一个
			ProxyIpModel m = proxyIps.remove(0);

			while (m != null && ((System.currentTimeMillis() - m.getCreateTime().getTime()) > durationOfValidity || m.getUseCount() >= maxRepeatCount) && !proxyIps.isEmpty()) {
				m = proxyIps.remove(0);
			}
			if (logger.isInfoEnabled()) {
				logger.info("simple pool size:" + proxyIps.size());
			}
			if (m != null) proxyTempIps.add(m);
			// 累计次数
			m.countUseCount();
			return m;
		} else if (proxyTempIps != null && !proxyTempIps.isEmpty()) {
			proxyIps.addAll(proxyTempIps);
			proxyTempIps.clear();
			if (proxyIps.size() < maxSize) { // 如果小于数量,则从网上下载
				proxyIps.addAll(this.downloadProxyIp(proxyIps.size(), this.poolInstanceId == ProxyIpSimplePool.DEFAULT_PROXY_POOL_INSTANCEID ? false : true));
			}
			return getProxyIp();
		} else {
			proxyIps.addAll(this.downloadProxyIp(maxSize, this.poolInstanceId == ProxyIpSimplePool.DEFAULT_PROXY_POOL_INSTANCEID ? false : true));
			return getProxyIp();
		}
	}

	private boolean pingIp(String ip) throws IOException {
		Process d = Runtime.getRuntime().exec("ping " + ip);
		d.getOutputStream().toString();
		return Boolean.TRUE;
	}

	public int getMaxSize() {
		return maxSize;
	}

	/**
	 * 增加一个代理IP到池中
	 *
	 * @param ip
	 */
	public synchronized void addIps(ProxyIpModel ip) {
		if (ip != null) {
			for (ProxyIpModel m : proxyIps) {// 过滤重复的
				if (m.getIp().equals(ip.getIp()) && m.getPort() == ip.getPort()) {
					return;
				}
			}
			proxyIps.add(ip);
		}
	}

	/**
	 * 增加多个代理IP到池中
	 *
	 * @param ips
	 */
	public synchronized void addIps(List<ProxyIpModel> ips) {
		if (ips != null && !ips.isEmpty()) {
			for (ProxyIpModel model : ips) {
				boolean flag = false;
				List<ProxyIpModel> tempList = proxyIps;
				for (ProxyIpModel m : tempList) {
					if (model.getIp().equals(m.getIp()) && model.getPort() == m.getPort()) {
						flag = true;
						break;
					}
				}
				tempList = null;
				if (!flag) proxyIps.add(model); // 不重复
			}
		}
	}

	public synchronized void clear() {
		if (proxyIps != null && !proxyIps.isEmpty()) {
			proxyIps.clear();
		}
	}

	public synchronized void destory() {
		if (proxyIps != null && !proxyIps.isEmpty()) {
			proxyIps.clear();
		}
		proxyIps = null;
	}

	/**
	 * 从网上下载代理IP .
	 *
	 * @param downloadNum 下载数量
	 * @param isInter 是否为国际IP
	 * @return
	 */
	private List<ProxyIpModel> downloadProxyIp(int downloadNum, boolean isInter) {
		List<ProxyIpModel> results = new ArrayList<ProxyIpModel>();
		List<String> ips = null;
		long stime = System.currentTimeMillis();
		ProxyIpModel model = null;
		try {
			ips = HttpDownProxyIp.getInstance().downloadIps(downloadNum, isInter);

			if (ips != null && !ips.isEmpty()) {
				for (String ip : ips) {
					model = new ProxyIpModel(ip.split(":")[0], Integer.valueOf(ip.split(":")[1]));
					model.setLocation(ProxyIpModel.IP_LOCATION_SPOOL);
					results.add(model);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new ProxyipProvideException(e);
		} finally {
			ips = null;
			model = null;
			if (logger.isInfoEnabled()) {
				logger.info(String.format("%s,耗时=%sms", (results.isEmpty() ? "没有获取到代理ip" : "获取到代理ip数量:" + results.size()), System.currentTimeMillis() - stime));
			}
		}
		return results;
	}

	public static void main(String[] args) {

	}
}